How to plot 2 m temperature data from ERA5

  • Run the cell below before running any other cell.Cell is commented.Uncomment it first before running it.
  • Then restart the kernel and run other cell
  • Keep in mind to perform these procedures each time you open this notebook.
In [1]:
# !apt-get install -qq libgdal-dev libproj-dev
# #!pip install --no-binary shapely shapely
# !pip install --no-binary shapely shapely --force
# !pip install cartopy
In [2]:
import xarray as xr
from datetime import datetime, timedelta
import numpy as np
import pandas as pd
import warnings
In [3]:
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt

About Data Download

Now we will use data from "ERA5 hourly data on single levels from 1940 to present" that is availble for free in climate data store website: cds.climate.copernicus.eu

The data I downloaded has the following specifications:

Product type:
Reanalysis

Variable:
2m temperature

Year:2023

Month:June, July

Day:
01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

Time:
00:00, 01:00, 02:00, 03:00, 04:00, 05:00, 06:00, 07:00, 08:00, 09:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00, 18:00, 19:00, 20:00, 21:00, 22:00, 23:00

Sub-region extraction:
North 29°, West 85°, South 18°, East 97°

Format:
NetCDF (experimental)

We can download the data directly using API. we need to follow the setps below to download the data:

Install the CDS API: Run the snippet below

In [4]:
!pip install cdsapi

Run the the snippet below to download the data:

Don't forget to change the output_folder location as you desire.

In [5]:
import cdsapi
import os

c = cdsapi.Client()

# Specify the folder where you want to save the downloaded data

output_folder = '/mnt/102ECBA62ECB8368/Academic journey/ML_HEATWAVE/Data/Test/'

# Ensure the output folder exists
os.makedirs(output_folder, exist_ok=True)

c.retrieve(
    'reanalysis-era5-single-levels',
    {
        'product_type': 'reanalysis',
        'variable': '2m_temperature',
        'year': '2023',
        'month': [
            '06', '07',
        ],
        'day': [
            '01', '02', '03',
            '04', '05', '06',
            '07', '08', '09',
            '10', '11', '12',
            '13', '14', '15',
            '16', '17', '18',
            '19', '20', '21',
            '22', '23', '24',
            '25', '26', '27',
            '28', '29', '30',
            '31',
        ],
        'time': [
            '00:00', '01:00', '02:00',
            '03:00', '04:00', '05:00',
            '06:00', '07:00', '08:00',
            '09:00', '10:00', '11:00',
            '12:00', '13:00', '14:00',
            '15:00', '16:00', '17:00',
            '18:00', '19:00', '20:00',
            '21:00', '22:00', '23:00',
        ],
        'area': [
            29, 85, 18,
            97,
        ],
        'format': 'netcdf',
    },
    os.path.join(output_folder,'t2m_data_for_exp.nc')
)
In [6]:
nc_file_path='/mnt/102ECBA62ECB8368/Academic journey/ML_HEATWAVE/Data/Test/t2m_data_for_exp.nc'

ds=xr.open_dataset(nc_file_path)
In [7]:
ds
Out[7]:
<xarray.Dataset>
Dimensions:    (longitude: 49, latitude: 45, expver: 2, time: 1464)
Coordinates:
  * longitude  (longitude) float32 85.0 85.25 85.5 85.75 ... 96.5 96.75 97.0
  * latitude   (latitude) float32 29.0 28.75 28.5 28.25 ... 18.5 18.25 18.0
  * expver     (expver) int32 1 5
  * time       (time) datetime64[ns] 2023-06-01 ... 2023-07-31T23:00:00
Data variables:
    t2m        (time, expver, latitude, longitude) float32 ...
Attributes:
    Conventions:  CF-1.6
    history:      2023-08-28 12:09:53 GMT by grib_to_netcdf-2.25.1: /opt/ecmw...

expver=1 means ERA5 and expver=5 means ERA5T. Google to understand more.

Check the dimensions

In [8]:
ds.t2m.dims
Out[8]:
('time', 'expver', 'latitude', 'longitude')

Here we will use just era5(expver=1) data and we will use data for time = 2023-06-15T12:00:00

In [9]:
expver_slice=1 
desired_time = '2023-06-15T12:00:00'
temperature_data=ds.sel(expver=expver_slice,time=desired_time)
In [10]:
temperature_data
Out[10]:
<xarray.Dataset>
Dimensions:    (longitude: 49, latitude: 45)
Coordinates:
  * longitude  (longitude) float32 85.0 85.25 85.5 85.75 ... 96.5 96.75 97.0
  * latitude   (latitude) float32 29.0 28.75 28.5 28.25 ... 18.5 18.25 18.0
    expver     int32 1
    time       datetime64[ns] 2023-06-15T12:00:00
Data variables:
    t2m        (latitude, longitude) float32 ...
Attributes:
    Conventions:  CF-1.6
    history:      2023-08-28 12:09:53 GMT by grib_to_netcdf-2.25.1: /opt/ecmw...

Now we have data for 12PM,June 15,2023.We can plot this data in two ways

  • Directly from the data
  • Creating a dataframe and plotting

Directly from the data

In [11]:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs


# Get latitude and longitude from xarray.Dataset
latitude = temperature_data['latitude'].values
longitude = temperature_data['longitude'].values

# Get t2m from xarray.Dataset
t2m = temperature_data.t2m

# Create a Cartopy PlateCarree projection
projection = ccrs.PlateCarree()

# Create a figure and axis with Cartopy projection
fig, ax = plt.subplots(subplot_kw={'projection': projection}, figsize=(12, 6))

# Plot the temperature data
pcolormesh=ax.pcolormesh(longitude,latitude,t2m,transform=projection,cmap='coolwarm')

# Add a colorbar
cbar = plt.colorbar(pcolormesh, ax=ax, orientation='vertical', pad=0.07, label='2 m temperature(K)')

# Add coastlines and gridlines
ax.coastlines()
ax.gridlines(draw_labels=True)
ax.add_feature(cartopy.feature.BORDERS)

# Customize plot properties
plt.title('ERA5 2 m Temperature')
plt.xlabel('Longitude')
plt.ylabel('Latitude')

# Show the plot
plt.show()

Creating a dataframe and plotting

In [12]:
import pandas as pd

# Get latitude,longitude and t2m from xarray.Dataset
latitude = temperature_data['latitude'].values
longitude = temperature_data['longitude'].values
t2m = np.array(temperature_data['t2m'])


# Reshape the 't2m' data to match the number of latitude and longitude points
reshaped_t2m = t2m.reshape(-1)

# Create a Pandas DataFrame
df = pd.DataFrame({
    'latitude': np.repeat(latitude, len(longitude)),
    'longitude': np.tile(longitude, len(latitude)),
    't2m': reshaped_t2m
})
In [13]:
df
Out[13]:
latitude longitude t2m
0 29.0 85.00 280.980835
1 29.0 85.25 280.084351
2 29.0 85.50 281.041992
3 29.0 85.75 281.098175
4 29.0 86.00 281.865753
... ... ... ...
2200 18.0 96.00 300.598450
2201 18.0 96.25 300.289429
2202 18.0 96.50 300.953735
2203 18.0 96.75 301.436249
2204 18.0 97.00 299.697845

2205 rows × 3 columns

In [14]:
# Import
warnings.filterwarnings("ignore")

# Get the latitude and longitude values
unique_lat = df['latitude'].unique()
unique_lon = df['longitude'].unique()

# Reshape the t2m data into a 2D array matching the grid
t2m_array = df['t2m'].values.reshape(len(unique_lat), len(unique_lon))

# Create a Cartopy PlateCarree projection
projection = ccrs.PlateCarree()

# Create a figure and axis
fig, ax = plt.subplots(subplot_kw={'projection': projection}, figsize=(12, 6))

# Plot the temperature data using pcolormesh
pcolormesh = ax.pcolormesh(unique_lon, unique_lat, t2m_array, transform=projection, cmap='coolwarm')

# Add colorbar
cbar = plt.colorbar(pcolormesh, ax=ax, orientation='vertical', pad=0.05, label='Temperature (K)')

# Set title and labels
ax.set_title('ERA5 2m Temperature')
ax.set_xlabel('Longitude')
ax.set_ylabel('Latitude')

# Add coastlines and gridlines
ax.coastlines()
ax.add_feature(cfeature.BORDERS)
ax.gridlines(draw_labels=True)

# Show the plot
plt.show()

A Beautiful plotting

In [15]:
projection = ccrs.PlateCarree()

# Create a figure and axis with Cartopy projection
fig, ax = plt.subplots(subplot_kw={'projection': projection})

# Plot the temperature data using scatter plot
scatter = ax.scatter(df['longitude'], df['latitude'], c=df['t2m'], cmap='coolwarm', s=10, transform=projection)

# Add coastlines and gridlines
ax.coastlines()
ax.gridlines(draw_labels=True)
ax.add_feature(cfeature.BORDERS)

# Customize plot properties
plt.title('Temperature Distribution')
plt.xlabel('Longitude')
plt.ylabel('Latitude')

# Add a colorbar using the scatter mappable
cbar = plt.colorbar(scatter)
cbar.set_label('Temperature')

# Show the plot
plt.show()
In [ ]:

In [ ]:

In [ ]: